﻿using System;
using System.Collections.Generic;
using System.Linq;

namespace Gmantis.Controls.DataGrid
{
    internal class DataGridSortManager
    {
        // Fields
        private DataGridColumn[] _sortedColumns;

        // Events
        public event EventHandler SortChanged;

        // Methods
        internal DataGridSortManager(DataGridModel model)
        {
            this.Model = model;
        }

        public void InvalidateSortedColumns()
        {
            this._sortedColumns = null;
        }

        private void OnSortChanged()
        {
            if (this.SortChanged != null)
            {
                this.SortChanged(this, new EventArgs());
            }
        }

        public void SetCurrentSortedColumns(DataGridColumnValue<DataGridSortDirection>[] sortedColumns)
        {
            List<DataGridColumnValue<DataGridSortDirection>> list = new List<DataGridColumnValue<DataGridSortDirection>>();
            foreach (DataGridColumn column in this.SortedColumns)
            {
                list.Add(new DataGridColumnValue<DataGridSortDirection>(column, column.SortState.Direction));
            }
            int num = 0;
            bool flag = false;
            foreach (DataGridColumnValue<DataGridSortDirection> value2 in sortedColumns)
            {
                DataGridColumn column2 = value2.Column;
                DataGridSortDirection direction = value2.Value;
                flag |= (column2.SortState.Index != num) || (column2.SortState.Direction != direction);
                column2.SortState.Set(direction, new int?(num++));
            }
            DataGridColumn[] columnArray2 = this.SortedColumns;
            for (int i = 0; i < columnArray2.Length; i++)
            {
                Func<DataGridColumnValue<DataGridSortDirection>, bool> predicate = null;
                DataGridColumn column = columnArray2[i];
                if (predicate == null)
                {
                    predicate = pair => pair.Column == column;
                }
                if (sortedColumns.Where<DataGridColumnValue<DataGridSortDirection>>(predicate).Count<DataGridColumnValue<DataGridSortDirection>>() == 0)
                {
                    int? index = null;
                    column.SortState.Set(DataGridSortDirection.None, index);
                    flag = true;
                }
            }
            this.InvalidateSortedColumns();
            if (flag)
            {
                DataGridSortChangedEventArgs e = new DataGridSortChangedEventArgs(sortedColumns, list.ToArray());
                this.OnSortChanged();
                this.Model.DataGrid.OnSortChanged(e);
            }
        }

        public void SortBy(bool preservePreviousSorting, params DataGridColumnValue<DataGridSortDirection>[] columns)
        {
            DataGridColumnValue<DataGridSortDirection>[] valueArray = columns;
            if (preservePreviousSorting)
            {
                List<DataGridColumnValue<DataGridSortDirection>> source = new List<DataGridColumnValue<DataGridSortDirection>>();
                foreach (DataGridColumn column in this.SortedColumns)
                {
                    source.Add(new DataGridColumnValue<DataGridSortDirection>(column, column.SortState.Direction));
                }
                DataGridColumnValue<DataGridSortDirection>[] valueArray2 = columns;
                for (int i = 0; i < valueArray2.Length; i++)
                {
                    Func<DataGridColumnValue<DataGridSortDirection>, bool> predicate = null;
                    DataGridColumnValue<DataGridSortDirection> col = valueArray2[i];
                    if (predicate == null)
                    {
                        predicate = si => si.Column == col.Column;
                    }
                    DataGridColumnValue<DataGridSortDirection> value2 = source.FirstOrDefault<DataGridColumnValue<DataGridSortDirection>>(predicate);
                    if (value2 == null)
                    {
                        source.Add(col);
                    }
                    else
                    {
                        value2.Value = col.Value;
                    }
                }
                valueArray = source.ToArray();
            }
            DataGridSortChangingEventArgs e = new DataGridSortChangingEventArgs(valueArray);
            this.Model.DataGrid.OnSortChanging(e);
            if (!e.Cancel)
            {
                if (!this.Model.DataGrid.IsSortingRowsAllowed)
                {
                    throw new DataGridSortException("Sorting rows is not allowed.");
                }
                try
                {
                    this.Model.DataConnection.SortDescriptions = (from si in valueArray
                                                                  where ((DataGridSortDirection)si.Value) != DataGridSortDirection.None
                                                                  select si).ToArray<DataGridColumnValue<DataGridSortDirection>>();
                }
                catch (Exception exception)
                {
                    throw new DataGridSortException("There was an error when sorting rows.", exception);
                }
            }
        }

        // Properties
        private DataGridModel Model { get; set; }

        public DataGridColumn[] SortedColumns
        {
            get
            {
                if (this._sortedColumns == null)
                {
                    this._sortedColumns = (from column in this.Model.Columns
                                           where (column.SortState.Direction != DataGridSortDirection.None) && !string.IsNullOrEmpty(column.ActualSortMemberPath)
                                           orderby column.SortState.Index
                                           select column).ToArray<DataGridColumn>();
                }
                return this._sortedColumns;
            }
        }
    }
}
